package wiEngine;

import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * expands of schedule. extends from ScheduledThreadPoolExecutor
 */
public class WiSchedulerThreadPoolExecutor extends ScheduledThreadPoolExecutor{

    static int corePoolDefault = 0;
    static int maxCorePoolDefault = 100;
    private long _startTime = -1;
    private long _finishTime = -1;

    public WiSchedulerThreadPoolExecutor() {
	super(corePoolDefault);
	setMaximumPoolSize(maxCorePoolDefault);
	setKeepAliveTime(1, TimeUnit.MILLISECONDS);
	allowCoreThreadTimeOut(true);
    }
    /**
     * @param corePool: number queue of threads in pool
     */
    public WiSchedulerThreadPoolExecutor(int corePool) {
	super(corePool);
	setMaximumPoolSize(maxCorePoolDefault);
    }
    
    /**
     * schedule an event (runnable) at timeAt with time unit.
     * @param run: event
     * @param timeUnit :unit of time (get from current speed)
     */
    @Override
    public ScheduledFuture<?> schedule(Runnable run, long timeAt, TimeUnit timeUnit) {
	return super.schedule(run, timeAt, timeUnit);
    }
    
    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
	return super.scheduleAtFixedRate(command, initialDelay, period, unit);
    }

    @Override
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
	return super.scheduleWithFixedDelay(command, initialDelay, delay, unit);
    }
    // simple pauseable feature
    private boolean isPaused;
    private ReentrantLock pauseLock = new ReentrantLock();
    private Condition unpaused = pauseLock.newCondition();
    /**
     * callback for pause/resume
     */
    @Override
    protected void beforeExecute(Thread t, Runnable r) {
	super.beforeExecute(t, r);
	pauseLock.lock();
	try {
	    while (isPaused) {
		unpaused.await();
	    }
	} catch (InterruptedException ie) {
	    t.interrupt();
	} finally {
	    pauseLock.unlock();
	}
    }
    /**
     * handle a clock to pause queue threads.
     */
    public void pause() {
	pauseLock.lock();
	try {
	    isPaused = true;
	} finally {
	    pauseLock.unlock();
	}
    }
    /**
     * release handle a clock to resume queue threads.
     */
    public void resume() {
	pauseLock.lock();
	try {
	    isPaused = false;
	    unpaused.signalAll();
	} finally {
	    pauseLock.unlock();
	}
    }
    
    public long getStartTime() {
	return _startTime;
    }

    public long getFinishTime() {
	return _finishTime;
    }

    public void setStartTime(long startTime) {
	this._startTime = startTime;
    }

    public void setFinishTime(long finishTime) {
	this._finishTime = finishTime;
    }
}
